home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 037a / mou_rout.zip / MOU.C < prev    next >
Text File  |  1991-01-08  |  25KB  |  792 lines

  1. /*****************************************************************************
  2.  * PROJECT:  Mouse routines with 'real' graphic cursor in text mode.
  3.  *****************************************************************************
  4.  * MODULE:  MOU.C
  5.  *****************************************************************************
  6.  * DESCRIPTION:
  7.  *   Main file for the mouse routines.
  8.  *
  9.  *****************************************************************************
  10.  * MODIFICATION NOTES:
  11.  *    Date     Author Comment
  12.  * 26-Oct-1990   dk   Initial file.
  13.  * 07-Jan-1991   dk   Fixed bugs and set up for release to Usenet.
  14.  *****************************************************************************
  15.  *
  16.  * DISCLAIMER:
  17.  *
  18.  * Programmers may incorporate any or all code into their programs,
  19.  * giving proper credit within the source. Publication of the
  20.  * source routines is permitted so long as proper credit is given
  21.  * to Dave Kirsch.
  22.  *
  23.  * Copyright (C) 1990, 1991 by Dave Kirsch.  You may use this program, or
  24.  * code or tables extracted from it, as desired without restriction.
  25.  * I can not and will not be held responsible for any damage caused from
  26.  * the use of this software.
  27.  *
  28.  *****************************************************************************
  29.  * This source works with Turbo C 2.0 and MSC 6.0 and above.
  30.  *****************************************************************************/
  31.  
  32. #ifdef __TURBOC__
  33. #pragma inline
  34. #endif
  35.  
  36. #include <stdio.h>
  37. #include <dos.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40.  
  41. #include "mou.h"
  42.  
  43. #define HEIGHT 16
  44.  
  45. word mousehidden = 0;           /* Is the mouse on? Additive flag */
  46. boolean mouseinstalled = FALSE; /* Is the mouse installed? */
  47.  
  48. volatile int mousex, mousey; /* Character position of mouse */
  49.  
  50. #ifndef __TURBOC__
  51. STATIC word _based(_segname("_CODE")) DGroupSeg;
  52. #endif
  53.  
  54. STATIC volatile int mbufin = 0, mbufout = 0; /* Mouse buffer pointers */
  55.  
  56. STATIC word mousefreeze = 0;           /* Is mouse frozen in place? */
  57.  
  58. STATIC MOUINFOREC mbuf[MOUSEBUFFERSIZE]; /* Mouse buffer */
  59.  
  60. /* Save information for non EGA/VGA */
  61. STATIC word oldword;
  62. STATIC word newword;
  63. STATIC boolean saved = FALSE;
  64. STATIC word oldmx, oldmy;
  65.  
  66. /* Save information for EGA/VGA displays */
  67. STATIC boolean egavga = FALSE; /* Do we have an EGA/VGA adapter? */
  68. STATIC byte savechars[3][3]; /* The saved characters we overwrote */
  69. STATIC dword mousecursormask[HEIGHT] =  {
  70.   0x00000000L,  /*0000000000000000*/
  71.   0x40000000L,  /*0100000000000000*/
  72.   0x60000000L,  /*0110000000000000*/
  73.   0x70000000L,  /*0111000000000000*/
  74.   0x78000000L,  /*0111100000000000*/
  75.   0x7c000000L,  /*0111110000000000*/
  76.   0x7e000000L,  /*0111111000000000*/
  77.   0x7f000000L,  /*0111111100000000*/
  78.   0x7f800000L,  /*0111111110000000*/
  79.   0x7f000000L,  /*0111111100000000*/
  80.   0x7c000000L,  /*0111110000000000*/
  81.   0x46000000L,  /*0100011000000000*/
  82.   0x06000000L,  /*0000011000000000*/
  83.   0x03000000L,  /*0000001100000000*/
  84.   0x03000000L,  /*0000001100000000*/
  85.   0x00000000L   /*0000000000000000*/
  86. };
  87.  
  88. STATIC dword mousescreenmask[HEIGHT] =  {
  89.   0x3fffffffL,  /*0011111111111111*/
  90.   0x1fffffffL,  /*0001111111111111*/
  91.   0x0fffffffL,  /*0000111111111111*/
  92.   0x07ffffffL,  /*0000011111111111*/
  93.   0x03ffffffL,  /*0000001111111111*/
  94.   0x01ffffffL,  /*0000000111111111*/
  95.   0x00ffffffL,  /*0000000011111111*/
  96.   0x007fffffL,  /*0000000001111111*/
  97.   0x003fffffL,  /*0000000000111111*/
  98.   0x007fffffL,  /*0000000001111111*/
  99.   0x01ffffffL,  /*0000000111111111*/
  100.   0x10ffffffL,  /*0001000011111111*/
  101.   0xb0ffffffL,  /*1011000011111111*/
  102.   0xf87fffffL,  /*1111100001111111*/
  103.   0xf87fffffL,  /*1111100001111111*/
  104.   0xfcffffffL   /*1111110011111111*/
  105. };
  106.  
  107. STATIC byte chardefs[32 * 9]; /* 9 character definitons. */
  108. STATIC word mousepx, mousepy; /* Mouse pixel coordinates */
  109.  
  110. STATIC boolean conditionalhidemouse = FALSE;
  111. STATIC word conx1, cony1, conx2, cony2;
  112.  
  113. STATIC word vseg; /* Segment of video ram. */
  114. STATIC word mcols, mrows;
  115. STATIC byte savevmode;
  116.  
  117. STATIC int maxx, maxy;
  118.  
  119. STATIC boolean desqview = FALSE;
  120.  
  121. #define POKEATTRIB(x, y, a) pokeb(vseg, (y) * (mcols * 2) + ((x) << 1) + 1, a)
  122. #define PEEKATTRIB(x, y)    peekb(vseg, (y) * (mcols * 2) + ((x) << 1) + 1)
  123.  
  124. #define POINTS *((byte far *) 0x00000485)
  125. #define COLS *((byte far *) 0x0040004AL)
  126. #define ROWS *((byte far *) 0x00400084L)
  127.  
  128. #define DEFCHAR 0xd0
  129.  
  130. /*********************************************************************/
  131. /* Mon 07-Jan-1991 - dk                                              */
  132. /*                                                                   */
  133. /*  Plot the cursor on the screen, save background, draw grid, etc.  */
  134. /*                                                                   */
  135. /*********************************************************************/
  136. PRIVATE void LOCAL FAST plotegavgacursor(int func)
  137. {
  138. word off;
  139. word width, height, i, j;
  140. word disp;
  141. word x, y;
  142. static int lsavex = 0, lsavey = 0;
  143. static int savedcur = FALSE;
  144.  
  145.   switch (func) {
  146.     case 0 : /* erase grid, put back save info */
  147.       if (!savedcur)
  148.         printf("Request to erase the cursor that wasn't saved!!\n");
  149.       savedcur = FALSE;
  150.       x = lsavex;
  151.       y = lsavey;
  152.       break;
  153.     case 1 : /* draw grid */
  154.       x = mousex;
  155.       y = mousey;
  156.       if (x != lsavex || y != lsavey)
  157.         printf("Request to draw cursor where we didn't save it!!!\n");
  158.       break;
  159.     case 2 : /* save grid */
  160.       if (savedcur)
  161.         printf("Request to save grid when is wasn't erased!!\n");
  162.       savedcur = TRUE;
  163.       lsavex = x = mousex;
  164.       lsavey = y = mousey;
  165.       break;
  166.   }
  167.  
  168.   width = mcols - x;
  169.   if (width > 3)
  170.     width = 3;
  171.   height = mrows - y;
  172.   if (height > 3)
  173.     height = 3;
  174.  
  175.   off = y * (mcols * 2) + x * 2;
  176.   disp = (mcols * 2) - width * 2;
  177.  
  178.   switch (func) {
  179.     case 0 : /* erase grid, put back save info */
  180.       for (i = 0; i < height; i++, off += disp)
  181.         for (j = 0; j < width; j++, off += 2)
  182.           pokeb(vseg, off, savechars[i][j]);
  183.       break;
  184.     case 1 : /* draw grid. */
  185.       for (i = 0; i < height; i++, off += disp)
  186.         for (j = 0; j < width; j++, off += 2)
  187.           pokeb(vseg, off, DEFCHAR + i * 3 + j);
  188.       break;
  189.     case 2 : /* save grid. */
  190.       for (i = 0; i < height; i++, off += disp)
  191.         for (j = 0; j < width; j++, off += 2)
  192.           savechars[i][j] = peekb(vseg, off);
  193.       break;
  194.   }
  195. }
  196.  
  197. PRIVATE void LOCAL FAST drawegavgacursor(void)
  198. {
  199. word off;
  200. word points;
  201. int i, j;
  202. word s1, s2, s3;
  203. dword *defs;
  204. dword *masks;
  205. word shift;
  206. dword addmask;
  207.  
  208.   plotegavgacursor(2); /* Save current grid that is there. */
  209.  
  210.   points = POINTS;
  211.  
  212.   /* Time for some assembler.  Program the EGA/VGA Sequencer and Graphics
  213.      Controller for direct access to the character definition tables.
  214.      Then read in the definitions for the characters we are changing, AND
  215.      the screen mask, then OR the cursor mask to them.  Then copy those
  216.      defintions into the location of the mouse cursor defintions
  217.      and set the Sequencer and Graphics Controller back to normal <whew!>.
  218.   */
  219.  
  220.   /* Program the Sequencer */
  221.  
  222.   asm pushf; /* Disable interrupts */
  223.   asm cli;
  224.   asm mov dx, 3c4h; /* Sequencer port address */
  225.   asm mov ax, 0704h; /* Sequential addressing */
  226.   asm out dx, ax;
  227.  
  228.   /* Program the Graphics Controller */
  229.   asm mov dx, 3ceh; /* Graphics Controller port address */
  230.   asm mov ax, 0204h; /* Select map 2 for CPU reads */
  231.   asm out dx, ax;
  232.   asm mov ax, 0005h; /* Disable odd-even addressing */
  233.   asm out dx, ax;
  234.   asm mov ax, 0406h; /* Map starts at A000:0000 (64K mode) */
  235.   asm out dx, ax;
  236.   asm popf;
  237.  
  238.   /* Ok, now we have direct access to the character defintion tables, copy
  239.      over the defintions for the characters we are changing */
  240.  
  241.   off = 0;
  242.   for (i = 0; i < 9; i += 3) { /* Grid is three characters high. */
  243.     s1 = ((byte *)savechars)[i    ] * 32;
  244.     s2 = ((byte *)savechars)[i + 1] * 32;
  245.     s3 = ((byte *)savechars)[i + 2] * 32;
  246.     for (j = 0; j < points; j++) {
  247.       off++; /* 4th byte, that we don't need. */
  248.       chardefs[off++] = peekb(0xa000, s3++);
  249.       chardefs[off++] = peekb(0xa000, s2++);
  250.       chardefs[off++] = peekb(0xa000, s1++);
  251.     }
  252.   }
  253.  
  254.   /* Ok, we've got the defintions for the characters that we are drawing the
  255.      cursor on.  AND the screen mask and OR the cursor mask to them, thereby
  256.      'drawing' the cursor.  Since the cursor is 16 pixels wide and 16 pixels
  257.      high, we have to save a 3 by 3 character grid where the mouse cursor is
  258.      going.  We use dwords (32 bits) to do the bit AND and OR.  This could
  259.      be made alot faster on a 386 by using 32 bit registers. */
  260.  
  261.   shift = mousepx % 8;
  262.   addmask = 0xff000000L << (8 - shift);
  263.  
  264.   masks = mousescreenmask;
  265.   defs = ((dword *)chardefs) + mousepy % points;
  266.   for (i = 0; i < HEIGHT; i++)
  267.     *defs++ &= (*masks++ >> shift) | addmask;
  268.  
  269.   masks = mousecursormask;
  270.   defs = ((dword *)chardefs) + mousepy % points;
  271.   for (i = 0; i < HEIGHT; i++)
  272.     *defs++ |= *masks++ >> shift;
  273.  
  274.   /* Ok, Everything is setup, now copy the modifed character definitions
  275.      to their new location. */
  276.  
  277.   asm mov dx, 3c4h; /* Sequencer port address */
  278.   asm mov ax, 0402h; /* CPU writes only to map 2 */
  279.   asm out dx, ax;
  280.  
  281.   off = 0;
  282.   for (i = 0; i < 9; i += 3) { /* Grid is three characters high. */
  283.     s1 = (DEFCHAR + i    ) * 32;
  284.     s2 = (DEFCHAR + i + 1) * 32;
  285.     s3 = (DEFCHAR + i + 2) * 32;
  286.     for (j = 0; j < points; j++) {
  287.       off++; /* 4th byte, that we don't need. */
  288.       pokeb(0xa000, s3++, chardefs[off++]);
  289.       pokeb(0xa000, s2++, chardefs[off++]);
  290.       pokeb(0xa000, s1++, chardefs[off++]);
  291.     }
  292.   }
  293.  
  294.   /* Ok, put the Sequencer and Graphics Controller back to normal */
  295.  
  296.   /* Program the Sequencer */
  297.   asm pushf; /* Disable interrupts */
  298.   asm cli;
  299.   asm mov dx, 3c4h; /* Sequencer port address */
  300.   asm mov ax, 0302h; /* CPU writes to maps 0 and 1 */
  301.   asm out dx, ax;
  302.   asm mov ax, 0304h; /* Odd-even addressing */
  303.   asm out dx, ax;
  304.  
  305.   /* Program the Graphics Controller */
  306.   asm mov dx, 3ceh; /* Graphics Controller port address */
  307.   asm mov ax, 0004h; /* Select map 0 for CPU reads */
  308.   asm out dx, ax;
  309.   asm mov ax, 1005h; /* Enable odd-even addressing */
  310.   asm out dx, ax;
  311.   asm sub ax, ax;
  312.   asm mov es, ax; /* Segment 0 */
  313.   asm mov ax, 0e06h; /* Map starts at B800:0000 */
  314.   asm mov bl, 7;
  315.   asm cmp es:[49h], bl; /* Get current video mode */
  316.   asm jne notmono;
  317.   asm mov ax, 0806h; /* Map starts at B000:0000 */
  318. notmono:
  319.   asm out dx, ax;
  320.   asm popf;
  321.  
  322.   /* Ok, now put the bytes on the screen */
  323.  
  324.   plotegavgacursor(1); /* Plot the new grid on the screen. */
  325. }
  326.  
  327. /*******************************************************/
  328. /* 27-Oct-1990 - dk                                    */
  329. /*                                                     */
  330. /*  This function checks for the presense of EGA/VGA.  */
  331. /*                                                     */
  332. /*******************************************************/
  333. PRIVATE boolean LOCAL FAST isegavga(void)
  334. {
  335.   asm mov ax, 1a00h; /* ROM BIOS video function 1ah -- Read Display Code */
  336.   asm int 10h;
  337.   asm cmp ah, 1ah; /* Is this call supported? */
  338.   asm je checkega; /* Not supported */
  339.   asm cmp bl, 7; /* VGA w/monochrome display? */
  340.   asm je isvga; /* Yup. */
  341.   asm cmp bl, 8; /* VGA w/color display? */
  342.   asm jne checkega; /* Nope */
  343. isvga:
  344.   return TRUE; /* EGA/VGA is installed */
  345. checkega:
  346.   asm mov ah, 12h; /* EGA BIOS function */
  347.   asm mov bl, 10h;
  348.   asm int 10h;
  349.   asm cmp bl, 10h; /* Is EGA BIOS present? */
  350.   asm jne isvga; /* There is an EGA in the system. */
  351.   return FALSE; /* Not EGA or VGA in system. */
  352. }
  353.  
  354. /************************************************/
  355. /* 26-Oct-1990 - dk                             */
  356. /*                                              */
  357. /*  Mouse handler -- called from mouse driver.  */
  358. /*                                              */
  359. /************************************************/
  360. PRIVATE void far mousehandler(void)
  361. /* This function is called whenever a button is pressed.  Do not call this
  362.    function directly!!
  363. */
  364. {
  365. register int conditionmask;
  366.  
  367.   /* Get our data segment */
  368.   asm push ds
  369. #ifdef __TURBOC__
  370.   asm push ax
  371.   asm mov ax, DGROUP
  372.   asm mov ds, ax
  373.   asm pop ax
  374. #else
  375.   asm mov ds, cs:DGroupSeg
  376. #endif
  377.  
  378.   asm mov conditionmask,ax
  379.  
  380.   if (!mousefreeze) {
  381.     /* save mouse info passed to us from driver */
  382.     asm mov mousex, cx
  383.     asm mov mousey, dx
  384.     asm mov mousepx, cx
  385.     asm mov mousepy, dx
  386.  
  387.     mousex /= 8; /* Characters are 8 pixels wide */
  388.     mousey /= POINTS; /* Scale mousey down */
  389.  
  390.     /* See if the mouse has moved. */
  391.     if (conditionmask & MOUSEMOVE) {
  392.       if (saved) {
  393.         if (egavga)
  394.           plotegavgacursor(0);
  395.         else
  396.           POKEATTRIB(oldmx, oldmy, oldword);
  397.         saved = FALSE;
  398.       }
  399.  
  400.       if (!mousehidden && conditionalhidemouse) /* Check to see if we need to hide */
  401.         if (mousex >= conx1 && mousex <= conx2 &&
  402.             mousey >= cony1 && mousey <= cony2) {
  403.           mousehidden++;
  404.           conditionalhidemouse = FALSE;
  405.         }
  406.  
  407.       if (!mousehidden) {
  408.         if (egavga)
  409.           drawegavgacursor();
  410.         else {
  411.           oldword = PEEKATTRIB(mousex, mousey);
  412.           _AX = oldword;  /* Prepare to rotate attrib byte */
  413.           asm and al, 0f7h; /* Clear high bit */
  414.           asm mov cl, 4   /* We want to rotate 4 bits */
  415.           asm rol al, cl  /* Rotate it */
  416.           newword = _AX;
  417.  
  418.           POKEATTRIB(mousex, mousey, newword); /* Write out new mouse cursor */
  419.         }
  420.  
  421.         oldmx = mousex;
  422.         oldmy = mousey;
  423.         saved = TRUE;
  424.  
  425.       }
  426.     }
  427.   }
  428.  
  429.   /* Now, see if a mouse button was whacked */
  430.   if (conditionmask & ~MOUSEMOVE)
  431.     if (((mbufin + 1) % MOUSEBUFFERSIZE) == mbufout) { /* Buffer full? */
  432.       sound(1760); /* Make some noise. */
  433.       delay(10);
  434.       nosound();
  435.     } else {
  436.       mbuf[mbufin].buttonstat = conditionmask & ~MOUSEMOVE;
  437.       mbuf[mbufin].cx = mousex;
  438.       mbuf[mbufin].cy = mousey;
  439.       mbuf[mbufin].shiftstate = peekb(0, 0x417); /* Get shift byte */
  440.       mbufin = (mbufin + 1) % MOUSEBUFFERSIZE;
  441.     }
  442.  
  443.   asm pop ds;
  444. }
  445.  
  446. /************************************/
  447. /* 26-Oct-1990 - dk                 */
  448. /*                                  */
  449. /*  Initialize the mouse routines.  */
  450. /*                                  */
  451. /************************************/
  452. void FAST MOUinit(void)
  453. {
  454. byte v;
  455. word points;
  456.  
  457. #ifndef __TURBOC__
  458.   asm mov cs:DGroupSeg,ds   /* save for interrupt handler to use */
  459. #endif
  460.  
  461.   asm sub ax,ax;    /* Mouse driver function 0 -- reset and detect */
  462.   asm int 33h
  463.   asm mov mouseinstalled, AX;
  464.  
  465.   if (mouseinstalled) { /* If a mouse is installed then activate driver */
  466.  
  467.     mousefreeze++; /* Make sure handler doesn't do things, yet */
  468.  
  469.     asm mov ax,0F00h;
  470.     asm int 10h;
  471.     asm mov v,al;
  472.  
  473.     if (v == 7) {
  474.       vseg = 0xb000u;
  475.     } else {
  476.       vseg = 0xb800u;
  477.       v = 3;
  478.     }
  479.  
  480.     if (ROWS == 0) { /* No value, assume 80x25. */
  481.       mrows = 25;
  482.       mcols = 80;
  483.       points = 8;
  484.     } else {
  485.       mrows = ROWS + 1;
  486.       mcols = COLS;
  487.       points = POINTS;
  488.     }
  489.  
  490.     /* Check to see if we are running in DESQview.  If so, don't try to
  491.        use the 'true' EGA/VGA cursor (DV doesn't like it at ALL). */
  492.  
  493.     asm mov ax, 2b01h;
  494.     asm mov cx, 4445h;
  495.     asm mov dx, 5351h;
  496.     asm int 21h;
  497.  
  498.     asm cmp al, 0ffh;
  499.     asm je notdv;
  500.  
  501.     desqview = TRUE;
  502.  
  503. notdv:
  504.  
  505.     /* Do we have an EGA or VGA?  If so, and we are not in monochrome mode
  506.        and we are not in DESQview then setup to draw a 'true' mouse cursor
  507.        on an EGA/VGA */
  508.     egavga = isegavga() && vseg != 0xb000u && !desqview;
  509.  
  510.     if (egavga) {
  511.       /* We are going to use our 'true' mouse cursor and we need pixel
  512.          resolution, not character resolution from the mouse driver
  513.          (In text mode, the mouse driver only returns coordinates in multiples
  514.          of 8, which we don't want.  We want multiples of 1, i.e. pixel
  515.          resolution).  To get the mouse driver to return coordinates in pixel
  516.          resolution, we 'trick' it into thinking it's in graphics mode by
  517.          setting the low memory byte indicating mode to mode 6 (CGA 640x200x2).
  518.          Then we reset the mouse driver.  The mouse driver will get the video
  519.          mode then act as if it was in graphics mode, not text mode. */
  520.       savevmode = peekb(0x40, 0x49);
  521.       pokeb(0x40, 0x49, 6); /* Does this work ?!?!?!?!? */
  522.  
  523.       /* Reset driver for change in video mode to take effect. */
  524.       asm sub ax,ax
  525.       asm int 33h
  526.  
  527.       /* Now that we've tricked the mouse driver into a grapics mode thereby
  528.          causing it to give us pixel resolutions, put the old mode back. */
  529.       pokeb(0x40, 0x49, savevmode);
  530.     }
  531.  
  532.     /* Set up max x and y ranges. */
  533.  
  534.     maxx = mcols * 8 - 1; /* Pixels horizontally */
  535.     maxy = mrows * points - 1; /* Pixels vertically */
  536.  
  537.     asm mov dx,maxx     /* Pixels horizontally */
  538.     asm mov ax,7        /* mouse driver function 7 -- set max x range */
  539.     asm sub cx,cx       /* Minimum range */
  540.     asm int 33h
  541.  
  542.     asm mov dx,maxy     /* Pixels veritcally */
  543.     asm mov ax,8        /* mouse driver function 8 -- set max y range */
  544.     asm sub cx,cx       /* Minimum range */
  545.     asm int 33h
  546.  
  547.     /* Now install user routine */
  548.  
  549.     asm mov ax,cs
  550.     asm mov es,ax
  551.     asm mov dx, offset mousehandler
  552.     /* Setup up bits for calling routine */
  553. #ifdef __TURBOC__
  554.     _CX = LEFTBPRESS | LEFTBRELEASE | RIGHTBPRESS | RIGHTBRELEASE | MOUSEMOVE;
  555. #else
  556.     asm mov cx,LEFTBPRESS | LEFTBRELEASE | RIGHTBPRESS | RIGHTBRELEASE | MOUSEMOVE;
  557. #endif
  558.     asm mov ax,12       /* Function 12 -- set user routine */
  559.     asm int 33h
  560.  
  561.     mousex = mousey = 0;
  562.     asm mov cx,mousex   /* xcoord */
  563.     asm mov dx,mousey   /* ycoord */
  564.     asm mov ax,4    /* mouse driver function 4 -- set mouse position */
  565.     asm int 33h
  566.  
  567.     MOUshow(); /* Call it twice just to make sure */
  568.  
  569.     mousefreeze--; /* Handler can get into business, now */
  570.   }
  571. }
  572.  
  573. /****************************/
  574. /* 26-Oct-1990 - dk         */
  575. /*                          */
  576. /*  Hide the mouse cursor.  */
  577. /*                          */
  578. /****************************/
  579. void FAST MOUhide(void)
  580. /* This function turns off the mouse cursor, the mouse still responds
  581.    to button presses */
  582. {
  583.   if (!mouseinstalled)
  584.     return;
  585.  
  586.   mousefreeze++; /* don't have the handler doing weird things */
  587.  
  588.   mousehidden++; /* indicate it's hidden now */
  589.  
  590.   if (saved) {
  591.     if (egavga)
  592.       plotegavgacursor(0);
  593.     else
  594.       POKEATTRIB(oldmx, oldmy, oldword);
  595.     saved = FALSE;
  596.   }
  597.  
  598.   mousefreeze--; /* reactivate handler */
  599. }
  600.  
  601. /****************************/
  602. /* 26-Oct-1990 - dk         */
  603. /*                          */
  604. /*  Show the mouse cursor.  */
  605. /*                          */
  606. /****************************/
  607. void FAST MOUshow(void)
  608. {
  609.   if (!mouseinstalled)
  610.     return;
  611.  
  612.   mousefreeze++; /* don't have the handler doing weird things */
  613.  
  614.   /* Just in case we were in a conditionalhide */
  615.   if (conditionalhidemouse) {
  616.     /* We were about to conditional hide, but we didn't, don't reactive
  617.        mouse cursor. */
  618.     conditionalhidemouse = FALSE;
  619.     mousefreeze--; /* Reactivate handler */
  620.     return;
  621.   }
  622.  
  623.   if (mousehidden)
  624.     mousehidden--;
  625.   else {
  626.     mousefreeze--; /* Reactivate handler */
  627.     return;  /* It isn't hidden! */
  628.   }
  629.  
  630.   if (mousehidden) {
  631.     mousefreeze--; /* reactivate handler */
  632.     return; /* still hidden! */
  633.   }
  634.  
  635.   /* Draw mouse cursor */
  636.  
  637.   if (egavga)
  638.     drawegavgacursor();
  639.   else {
  640.     oldword = PEEKATTRIB(mousex, mousey);
  641.     _AX = oldword;  /* Prepare to rotate attrib byte */
  642.     asm and al, 0f7h; /* Clear high bit */
  643.     asm mov cl, 4   /* We want to rotate 4 bits */
  644.     asm rol al, cl  /* Rotate it */
  645.     newword = _AX;
  646.  
  647.     POKEATTRIB(mousex, mousey, newword); /* Write out new mouse cursor */
  648.   }
  649.  
  650.   oldmx = mousex;
  651.   oldmy = mousey;
  652.   saved = TRUE;
  653.  
  654.   mousefreeze--; /* Reactivate handler */
  655. }
  656.  
  657. /*************************************************************/
  658. /* 27-Oct-1990 - dk                                          */
  659. /*                                                           */
  660. /*  Returns true if there is something in the mouse buffer.  */
  661. /*                                                           */
  662. /*************************************************************/
  663. boolean FAST MOUcheck(void)
  664. {
  665.   return mbufin != mbufout;
  666. }
  667.  
  668. /**************************************************************/
  669. /* 26-Oct-1990 - dk                                           */
  670. /*                                                            */
  671. /*  Take a copy of the mouse event at the head of the queue.  */
  672. /*                                                            */
  673. /**************************************************************/
  674. void FAST MOUpreview(MOUINFOREC *mouinforec)
  675. {
  676.   if (!mouseinstalled)
  677.     return;
  678.  
  679.   if (mbufin != mbufout) /* if something is in buffer */
  680.     *mouinforec = mbuf[mbufout];
  681.   else {
  682.     /* Nothing to pull, just report mouse position */
  683.     mouinforec -> cx = mousex;
  684.     mouinforec -> cy = mousey;
  685.     mouinforec -> buttonstat = 0;
  686.     mouinforec -> shiftstate = peekb(0, 0x417);
  687.   }
  688. }
  689.  
  690. /****************************************************************/
  691. /* 26-Oct-1990 - dk                                             */
  692. /*                                                              */
  693. /*  Get (and remove) the mouse event at the head of the queue.  */
  694. /*                                                              */
  695. /****************************************************************/
  696. void FAST MOUget(MOUINFOREC *mouinforec)
  697. {
  698.   if (!mouseinstalled)
  699.     return;
  700.  
  701.   if (mbufin != mbufout) { /* if something is in buffer */
  702.     if (mouinforec != NULL)
  703.       *mouinforec = mbuf[mbufout];
  704.     mbufout = (mbufout + 1) % MOUSEBUFFERSIZE;
  705.   } else {
  706.     /* Nothing to pull, just report mouse position */
  707.     mouinforec -> cx = mousex;
  708.     mouinforec -> cy = mousey;
  709.     mouinforec -> buttonstat = 0;
  710.     mouinforec -> shiftstate = peekb(0, 0x417);
  711.   }
  712. }
  713.  
  714. /**************************************/
  715. /* 26-Oct-1990 - dk                   */
  716. /*                                    */
  717. /*  Deinitialize the mouse routines.  */
  718. /*                                    */
  719. /**************************************/
  720. void FAST MOUdeinit(void)
  721. {
  722.   if (!mouseinstalled)
  723.     return;
  724.  
  725.   MOUhide();
  726.  
  727.   asm sub ax,ax
  728.   asm int 33h
  729. }
  730.  
  731. /**************************************************/
  732. /* 26-Oct-1990 - dk                               */
  733. /*                                                */
  734. /*  Returns the bits for the button status info.  */
  735. /*                                                */
  736. /**************************************************/
  737. word FAST MOUbuttonstatus(void)
  738. {
  739. word buts;
  740.  
  741.   if (!mouseinstalled)
  742.     return 0;
  743.  
  744.   asm mov ax,3
  745.   asm int 33h
  746.   asm mov buts,bx
  747.   return buts;
  748. }
  749.  
  750. /************************************************************************/
  751. /* 26-Oct-1990 - dk                                                     */
  752. /*                                                                      */
  753. /*  Hide the mouse *if* it enters a certain screen area, automatically. */
  754. /*                                                                      */
  755. /************************************************************************/
  756. void FAST MOUconditionalhide(int x1, int y1, int x2, int y2)
  757. {
  758.   if (!mouseinstalled)
  759.     return;
  760.  
  761.   mousefreeze++; /* hold the handler */
  762.  
  763.   if (mousehidden) {
  764.     mousefreeze--; /* reactivate handler */
  765.     return; /* already hidden! */
  766.   }
  767.  
  768.   conditionalhidemouse = TRUE;
  769.  
  770.   x1 -= 2;
  771.   if (x1 < 0)
  772.     x1 = 0;
  773.   y1 -= 2;
  774.   if (y1 < 0)
  775.     y1 = 0;
  776.   x2 += 2;
  777.   y2 += 2;
  778.  
  779.   conx1 = x1;
  780.   cony1 = y1;
  781.   conx2 = x2;
  782.   cony2 = y2;
  783.  
  784.   if (mousex >= conx1 && mousex <= conx2 &&
  785.       mousey >= cony1 && mousey <= cony2) {
  786.     conditionalhidemouse = FALSE; /* We've already hidden it */
  787.     MOUhide(); /* turn it off now if it's there. */
  788.   }
  789.  
  790.   mousefreeze--;
  791. }
  792.